package org.jslaughter.camera.plugin;

import org.jslaughter.event.eventtype.ExplosionEvent;
import org.jslaughter.event.eventtype.ExplosionListener;
import org.newdawn.slick.geom.Vector2f;
import org.nvframe.camera.Camera;
import org.nvframe.camera.plugin.CameraPlugin;
import org.nvframe.entity.Entity;
import org.nvframe.event.EventService;
import org.nvframe.event.eventtype.UpdateEvent;
import org.nvframe.event.eventtype.UpdateListener;

public class ShakyCamEffect implements CameraPlugin, ExplosionListener, UpdateListener {
	
	private Camera camera;
	private Entity focusEntity;
	
	private boolean shaking = false;
	private int offsetRange = 40;
	private float maxSkakeTime = 3000f;
	private float latency = 100f;
	private float skakeTime = 0;
	
	public ShakyCamEffect(Entity focusEntity) {
		this.focusEntity = focusEntity;
	}
	
	public void setCamera(Camera camera) {
		this.camera = camera;
		
		EventService.getInstance().addEventListener(this);
	}


	@Override
	public void onExplosion(ExplosionEvent event) {
		if(event.getTarget() != focusEntity) 
			return;
		
		newPosition = new Vector2f((float) (Math.random() * offsetRange), (float) (Math.random() * offsetRange));
		shaking = true;
	}
	
	private Vector2f velocity = new Vector2f(0, 0);
	private Vector2f newPosition;
	
	@Override
	public void onUpdate(UpdateEvent event) {
		if (!shaking)
	        return;

		float delta = event.getDelta();
		skakeTime += delta;

	    // reset camera after exeeding maxShakes
	    if (shaking && skakeTime >= maxSkakeTime) {
		   skakeTime = 0;
	       shaking = false;
	       newPosition = new Vector2f(0, 0);
	       System.out.println("done, bringing camera back to equilibrium");
	    }
	    
	    Vector2f localPosition = camera.getLocalPosition();
	    Vector2f diff = newPosition.copy().sub(localPosition);

	    //System.out.println("diff: " + diff);
	   
	    if(shaking && diff.x == 0 && diff.y  == 0) {
		    newPosition = new Vector2f((float) (Math.random() * offsetRange), (float) (Math.random() * offsetRange));
		    
		    if((Math.random() * 2) + 1 == 1)
		    	newPosition.negate();
	    }

		float cameraAX = (2 * (diff.x - velocity.x * latency)) / (latency * latency);
		float cameraAY = (2 * (diff.y - velocity.y * latency)) / (latency * latency);
		
		velocity.x += cameraAX * delta;
		velocity.y += cameraAY * delta;
		
		localPosition.x += velocity.x * delta;
		localPosition.y += velocity.y * delta;
		
	    camera.setLocalPosition(localPosition);
	}
	
}
